#pragma once

#include <cstdint>
#include <string>
#include <ctime>
#include "engine.hh"
#include "../corelib/util/http_parser.hh"

namespace kratos { namespace engine {

class Engine;

// User service interface
class Service {
public:
    // install it before startup
    // @param engine engine instance
    // @retval true
    // @retval false fail
    virtual bool install(Engine* engine) = 0;
    // uninstall it after stop
    // @retval true
    // @retval false fail
    virtual bool uninstall() = 0;
    // start service
    // @param engine engine instance
    // @retval true
    // @retval false start failed
    virtual bool start(Engine* engine) = 0;
    // stop service
    // @retval true
    // @retval false start failed
    virtual bool stop() = 0;
    // Returns module type
    virtual std::uint32_t getType() = 0;
    // invoke every cycle
    // @param millionseconds current timestamp in millionseconds
    virtual void onTick(std::time_t millionseconds) = 0;
    // invoked by engine when command reached
    // @param command command
    // @return result
    virtual std::string execute(const std::string& command) = 0;
    // invoked when path connected or accepted
    // @param pathID path ID
    // @param siteType grid type which path connect(accept) to(from)
    // @param userData user offerred user data
    virtual void onPathJoin(PathID pathID, SiteType siteType, UserData userData) = 0;
    // invoked when path find timed out
    // @param siteType grid type which path connect(accept) to(from)
    // @param userData user offerred user data
    virtual void onFindPathTimeout(SiteType siteType, UserData userData) = 0;
    // invoked by engine when path disconnected
    // @param pathID path ID
    // @param siteType grid type which path connect(accept) to(from)
    virtual void onPathDisjoin(PathID pathID, SiteType siteType) = 0;
    // invoked by engine when read a protobuf::Message from it
    // @param pathID path ID
    // @param siteType grid type which path connect(accept) to(from)
    // @param userData user offerred user data when call findPath()
    // @param data data stream
    // @param size data size in bytes
    virtual void onPathData(PathID pathID, SiteType siteType, const char* data, std::size_t size) = 0;
    // invoked by engine when the locator of entity changed
    // @param entityID entity ID
    // @param entityType entity type
    // @param from old locator path ID
    // @param to new locator path ID
    virtual void onLocatorChange(std::uint64_t entityID, std::uint32_t entityType, PathID from, PathID to) = 0;
    // invoked by engine when accept a gateway session
    // @param sessionID session ID
    virtual void onSessionJoin(SessionID sessionID) = 0;
    // invoked by engine when gateway session disconnected
    // @param sessionID session ID
    virtual void onSessionDisjoin(SessionID sessionID) = 0;
    // invoked by engine when read a protobuf::Message from it
    // @param sessionID session ID
    // @param data data stream
    // @param size data size in bytes
    virtual void onSessionData(SessionID sessionID, const char* data, std::size_t size) = 0;
    // invoked by engine when read a http request from it
    // @param sessionID session ID
    // @param httpProto http message
    virtual void onHttpData(SessionID sessionID, const kratos::util::HttpProto& httpProto) = 0;
    // invoked by engine when timer timeout
    // @param timerID timer ID
    virtual void onTimer(TimerHandle timerID) = 0;
    // invoked by engine when grid site has been connected or accepted
    // @param siteID grid site ID
    virtual void onSiteJoin(const grid::SiteID& siteID) = 0;
    // invoked by engine when grid site disconnecting
    // @param siteID grid site ID
    virtual void onSiteDisjoin(const grid::SiteID& siteID) = 0;
    // invoked by engine when received data
    // @param siteID grid site ID
    // @param data the pointer of received data
    // @param size the length of data
    virtual void onSiteData(const grid::SiteID& siteID, const char* data, std::size_t size) = 0;
    // Invoked by engine when locator path joined
    // @param pathID path ID
    virtual void onLocatorJoin(PathID pathID) = 0;
    // Invoked by engine when locator path broken
    // @param pathID path ID
    virtual void onLocatorDisjoin(PathID pathID) = 0;
    // Is started?
    virtual bool isStarted() = 0;
    // Setup service name
    virtual void setServiceName(const std::string& serviceName) = 0;
    // Invoked by engine when session connected
    virtual void onSessionConnected(SessionID sessionID, std::uint64_t userData) = 0;
};

}}
